package fr.jade.reflex.control.name;

import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.factory.InstantiationException;

import fr.jade.fraclite.InitializationContext;
import fr.jade.fraclite.control.name.BasicNameController;
import fr.jade.reflex.api.control.GenericAttributeNotificationController;
import fr.jade.reflex.api.control.NameNotificationController;
import fr.jade.reflex.api.control.ReflexController;
import fr.jade.reflex.util.Reflex;
import fr.jade.util.log.Logger;
import fr.jade.util.log.config.LogReflex;

/**
 * Provides an implementation of the
 * {@link org.objectweb.fractal.api.control.NameController} interface which
 * manages the causal connection with the dual level (i.e meta/execution) : Any
 * operation on the name of the current component is forwarded to the name
 * controller of dual component.
 * 
 * @author Fabienne Boyer
 * @contact Fabienne.Boyer@inrialpes.fr
 */

public class ReflexNameController extends BasicNameController implements NameNotificationController {

  /**
   * The <tt>weaveableRC</tt> field required by this mixin. This field is
   * supposed to reference the {@link ReflexController} interface of the
   * component to which this controller object belongs.
   */

  public ReflexController weaveableRC;
  
  public void initFcController(InitializationContext ic) throws InstantiationException {
    super.initFcController(ic);
    weaveableRC = (ReflexController) ic.getInterface("reflex-controller");
  }
  
  protected NameNotificationController getDualCtrl() {
    assert weaveableRC != null : "Component must have a ReflexController";
    Component dual = weaveableRC.getCmpRef();
    assert dual != null : "Component must have a dual";
    NameNotificationController dualCtrl = null;
    try {
      dualCtrl = Reflex.getNameNotificationController(dual);
    } catch (NoSuchInterfaceException ignored) {    }
    assert dualCtrl != null : "Dual component must have a name-notification-controller";
    return dualCtrl;
  }
    // -------------------------------------------------------------------------
    // Fields and methods added and overriden by the mixin class
    // -------------------------------------------------------------------------

    /**
     * Calls the overriden setFcName method and then notifies the dual level of
     * the operation.
     * 
     * @param name
     *            the new component name
     */
    public void setFcName(final String name) {
        NameNotificationController dualCtrl = getDualCtrl();
        // calls the overriden setFcName method
        setFcNameNotification(name);
        dualCtrl.setFcNameNotification(name);
    }

    /**
     * Calls the overriden setFcName method
     * 
     * @param name
     *            the new component name
     */
    public void setFcNameNotification(String name) {
        Logger.println(LogReflex.debug, "ReflexNameMixin.setFcNameNotification " + name);
        // calls the overriden setFcName method
        super.setFcName(name);
    }

}
